//
//  OSHttpManager.m
//  ZKCompetitionApp
//
//  Created by 凯朱 on 2019/8/24.
//

#import "OSHttpManager.h"
#import "YQNetworking.h"
#import "Reachability.h"
#import "AESCipher.h"
#import <CommonCrypto/CommonCrypto.h>
static  NSString *const kRequestFaildMessage = @"网络请求失败，请稍后重试";
static  NSString *const kWithoutNetworkMessage = @"客户端无有效的网络连接";
@interface OSHttpManager()

@end

@implementation OSHttpManager

//上传文件
+(void)uploadFilesWithParams:(NSData *)fileData finished:(OSRequiredFinished)finished{
    [YQNetworking setupTimeout:60];
    NSString *urlStr = [NSString stringWithFormat:@"%@/sign-api/upload",ROOT_URL];
    [YQNetworking uploadFileWithUrl:urlStr fileData:fileData type:@"png" name:@"file" mimeType:@"" progressBlock:nil successBlock:^(id response) {
        if (finished) finished(YES,response,@"0",@"上传文件成功");
    } failBlock:^(NSError *error) {
        if (finished) finished(NO,@{},@"-1",@"上传文件失败");
    }];
}

//上传视频文件
+(void)uploadVideoFilesWithParams:(NSData *)fileData finished:(OSRequiredFinished)finished{
    [YQNetworking setupTimeout:60];
    NSString *urlStr = [NSString stringWithFormat:@"%@/sign-api/upload",ROOT_URL];
    [YQNetworking uploadFileWithUrl:urlStr fileData:fileData type:@"mp4" name:@"file" mimeType:@"" progressBlock:nil successBlock:^(id response) {
        if (finished) finished(YES,response,@"0",@"上传文件成功");
    } failBlock:^(NSError *error) {
        if (finished) finished(NO,@{},@"-1",@"上传文件失败");
    }];
}

//修改个人头像
+(void)saveUserHeadWithParams:(NSData *)fileData finished:(OSRequiredFinished)finished{
    NSString *urlStr = [NSString stringWithFormat:@"%@/accumulation/v1/userAvatar",ROOT_URL];
    
    [YQNetworking uploadFileWithUrl:urlStr fileData:fileData type:@"png" name:@"file" mimeType:@"" progressBlock:nil successBlock:^(id response) {
        if (finished) finished(YES,response,@"0",@"信息修改成功");
    } failBlock:^(NSError *error) {
        if (finished) finished(NO,@{},@"-1",@"头像修改失败");
    }];
}


+(void)postWithPath:(NSString *)path params:(NSDictionary *)params finished:(OSRequiredFinished)finished{
    NSString *urlStr = [NSString stringWithFormat:@"%@%@",ROOT_URL,path];
    [self requestWithUrl:urlStr method:POST params:params finished:^(BOOL isSuccessed, id  _Nonnull result, NSString * _Nonnull code, NSString * _Nonnull message) {
        if (finished) finished(isSuccessed,result,code,message);
    }];
}

+(void)getWithPath:(NSString *)path params:(NSDictionary *)params finished:(OSRequiredFinished)finished{
    NSString *urlStr = [NSString stringWithFormat:@"%@%@",ROOT_URL,path];
    [self requestWithUrl:urlStr method:GET params:params finished:^(BOOL isSuccessed, id  _Nonnull result, NSString * _Nonnull code, NSString * _Nonnull message) {
        if (finished) finished(isSuccessed,result,code,message);
    }];
}



/*
 发起网络请求
 
 @param url url
 @param method 请求方式
 @param params 参数
 @param finished 完成回调
 */
+(void)requestWithUrl:(NSString *)url method:(OSRequestMethod)method params:(NSDictionary *)params finished:(OSRequiredFinished)finished{
  
    NSDictionary *paramsNew = [self insertBaseInfo:params];
    [YQNetworking setupTimeout:20];
    if (method == GET) {
        [YQNetworking getWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:paramsNew progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }else{
        [YQNetworking postWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:paramsNew progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }
}

/*
 发起网络请求json请求
 
 @param url url
 @param method 请求方式
 @param params 参数
 @param finished 完成回调
 */
+(void)requestJsonWithUrl:(NSString *)url method:(OSRequestMethod)method params:(NSDictionary *)params finished:(OSRequiredFinished)finished{
    NSDictionary *paramsNew = [self insertBaseInfo:params];
    [YQNetworking setupTimeout:20];
  
    if (method == GET) {
        [YQNetworking getWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:paramsNew progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }else{
        [YQNetworking postWithUrl:url refreshRequest:NO cache:NO jsonRequest:YES params:paramsNew progressBlock:nil successBlock:^(id response) {
            [self handleResultWithResponse:response error:nil finished:finished];
        } failBlock:^(NSError *error) {
            [self handleResultWithResponse:nil error:error finished:finished];
        }];
    }
}

+(NSDictionary *)insertBaseInfo:(NSDictionary *)params{
    NSMutableDictionary *newParams = [[NSMutableDictionary alloc] initWithDictionary:params];
    
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
//    NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
    NSString *bundleId = @"com.geniecredit.loanios";
    NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
    NSString *phoneModel = [UIDevice currentDevice].machineModelName;
    NSString *sysVer = [UIDevice currentDevice].systemVersion;
    NSString *time = [[NSDate date] timestamp2];
    NSString *md5Key = @"";
    NSString *appsFlyerId = @"";
    NSString *platform = @"ios";
    NSString *signStr = [NSString stringWithFormat:@"%@%@%@%@%@%@%@",time,md5Key,kToken,appsFlyerId,bundleId,app_Version,platform];
    NSString *sign = [signStr md5String];
    NSDictionary *baseInfo = @{@"platform":platform,
                               @"bundleId":bundleId,
                               @"app_package_name":@"",
                               @"app_version":app_Version,
                               @"version":app_Version,
                               @"register_type":@"ios",
                               @"device_name":phoneModel,
                               @"device":@"ios",
                               @"device_version":sysVer,
                               @"device_sn":@"",
                               @"app_name":@"",
                               @"channle":@"",
                               @"token":kToken,
                               @"appsFlyerId":appsFlyerId,
                               @"timestamp":time,
                               @"sign":sign};
    
    [newParams addEntriesFromDictionary:baseInfo];
    NSString *jsonStr = [OSTool objectToJson:newParams];
    NSString *key = [NSString dateStrFromDate:[NSDate date] formatStr:@"yyyyMMyyyyMMyyyy"];
    NSString *dataStr = [self encrypt:jsonStr withKey:key];
    NSDictionary *finalParams = @{@"data":dataStr};
    
    NSDictionary *header = @{@"appsFlyerId":@"",
                             @"version":app_Version,
                             @"timestamp":[[NSDate date] timestamp2],
                             @"sign":sign,
                             @"platform":@"IOS",
                             @"visit_source":@"IOS"};
    NSLog(@"请求参数 %@",newParams);
    NSLog(@"signStr = %@",signStr);
    [YQNetworking configHttpHeader:header];
    
    return finalParams;
}
#pragma mark - ————— 图片上传 <表单专用> —————

/**
 处理网络请求结果
 
 @param response 响应体
 @param error 错误
 */
+(void)handleResultWithResponse:(id)response error:(NSError *)error
                       finished:(OSRequiredFinished)finished{
    
    //请求错误
    if (error) {
        NSString *message = [self getNetworkErrorMessageWith:error.code];
        if (finished) finished(NO,@"",@"",message);
        return;
    }
    
  
    
    NSString *dataStr = response[@"data"];
    //解密
    NSString *key = [NSString dateStrFromDate:[NSDate date] formatStr:@"yyyyMMyyyyMMyyyy"];
    NSString *jsonStr = [self decrypt:dataStr withKey:key];
    NSDictionary *data = [OSTool dictionaryWithJsonStr:jsonStr];
    NSString *code = kSTRING(data[@"code"]);
    NSString *message = kSTRING(data[@"msg"]);
    
    if ([code isEqualToString:@"403100"] || [code isEqualToString:@"403100"] || [code isEqualToString:@"501"]) {
        [[OSUserManager sharedOSUserManager] clearUserData];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"loginStatusChange" object:nil];
        kShowToast(@"登录过期");
        return;
    }
    
    if ([code isEqualToString:@"200"]) {
        if (finished) finished(YES,data,code,message);
    }
    else{
        if (finished) finished(NO,data,code,message);
    }
}

+ (NSString *)decrypt:(NSString *)encryptedString withKey:(NSString *)key {
    // 将密钥转换为 NSData
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];

    // 将 Base64 编码的加密字符串转换为 NSData
    NSData *data = [[NSData alloc] initWithBase64EncodedString:encryptedString options:0];

    // 创建解密上下文
    CCCryptorRef cryptor = NULL;
    CCCryptorStatus status = CCCryptorCreate(kCCDecrypt,
                                             kCCAlgorithmAES,
                                             kCCOptionPKCS7Padding|kCCOptionECBMode,
                                             keyData.bytes,
                                             keyData.length,
                                             NULL, // IV 不需要
                                             &cryptor);

    if (status != kCCSuccess) {
        NSLog(@"Error creating decryptor: %d", status);
        return nil;
    }

    size_t bufferLength = data.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferLength);

    size_t decryptedLength = 0;
    status = CCCryptorUpdate(cryptor,
                             data.bytes,
                             data.length,
                             buffer,
                             bufferLength,
                             &decryptedLength);

    if (status != kCCSuccess) {
        NSLog(@"Error during decryption update: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    size_t finalLength = 0;
    status = CCCryptorFinal(cryptor,
                            (void *)((char *)buffer + decryptedLength),
                            bufferLength - decryptedLength,
                            &finalLength);

    if (status != kCCSuccess) {
        NSLog(@"Error during decryption finalization: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    decryptedLength += finalLength;
    NSData *decryptedData = [NSData dataWithBytesNoCopy:buffer length:decryptedLength];

    // 将 NSData 转换为 NSString
    NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];

    return decryptedString;
}

+ (NSString *)encrypt:(NSString *)plainText withKey:(NSString *)key {
    // 将密钥转换为 NSData
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    
    // 将明文字符串转换为 NSData
    NSData *data = [plainText dataUsingEncoding:NSUTF8StringEncoding];

    // 创建加密上下文
    CCCryptorRef cryptor = NULL;
    CCCryptorStatus status = CCCryptorCreate(kCCEncrypt,
                                             kCCAlgorithmAES,
                                             kCCOptionPKCS7Padding|kCCOptionECBMode,
                                             keyData.bytes,
                                             keyData.length,
                                             NULL, // IV 不适用 ECB 模式
                                             &cryptor);
    
    if (status != kCCSuccess) {
        NSLog(@"Error creating encryptor: %d", status);
        return nil;
    }

    size_t bufferLength = data.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferLength);
    
    size_t encryptedLength = 0;
    status = CCCryptorUpdate(cryptor,
                             data.bytes,
                             data.length,
                             buffer,
                             bufferLength,
                             &encryptedLength);
    
    if (status != kCCSuccess) {
        NSLog(@"Error during encryption update: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    size_t finalLength = 0;
    status = CCCryptorFinal(cryptor,
                            (void *)((char *)buffer + encryptedLength),
                            bufferLength - encryptedLength,
                            &finalLength);

    if (status != kCCSuccess) {
        NSLog(@"Error during encryption finalization: %d", status);
        free(buffer);
        CCCryptorRelease(cryptor);
        return nil;
    }

    encryptedLength += finalLength;
    NSData *encryptedData = [NSData dataWithBytesNoCopy:buffer length:encryptedLength];

    // 将加密后的 NSData 转换为 Base64 字符串
    NSString *base64String = [encryptedData base64EncodedStringWithOptions:0];

    return base64String;
}

+(NSData *)decryptData:(NSData *)data withKey:(NSData *)key{
    // 检查密钥长度
    if (key.length != kCCKeySizeAES128 && key.length != kCCKeySizeAES192 && key.length != kCCKeySizeAES256) {
        NSLog(@"Invalid key length");
        return nil;
    }
    
    size_t dataOutLength;
    NSMutableData *decryptedData = [NSMutableData dataWithLength:data.length];

    CCCryptorStatus result = CCCrypt(kCCDecrypt,
                                      kCCAlgorithmAES,
                                      kCCOptionPKCS7Padding, // 使用填充
                                      key.bytes,
                                      key.length,
                                      NULL, // ECB 模式不需要 IV
                                      data.bytes,
                                      data.length,
                                      decryptedData.mutableBytes,
                                      decryptedData.length,
                                      &dataOutLength);

    if (result == kCCSuccess) {
        decryptedData.length = dataOutLength; // 设置正确的长度
        return decryptedData;
    }
    return nil; // 解密失败
}

+(NSString*)coverFromHexDataToStr:(NSData*)hexData
{
    NSString* result;
    const unsigned char* dataBuffer = (const unsigned char*)[hexData bytes];
    if(!dataBuffer){
        return nil;
    }
    NSUInteger dataLength = [hexData length];
    NSMutableString* hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
    for(int i = 0; i < dataLength; i++){
        [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
    }
    result = [NSString stringWithString:hexString];
    return result;

}

+(NSString*)coverFromHexStringToStr:(NSString*)hexStr
{
    if (([hexStr length] % 2) != 0)
        return nil;
    
    NSMutableString *string = [NSMutableString string];
    
    for (NSInteger i = 0; i < [hexStr length]; i += 2) {
        
        NSString *hex = [hexStr substringWithRange:NSMakeRange(i, 2)];
        NSInteger decimalValue = 0;
        sscanf([hex UTF8String], "%x", &decimalValue);
        [string appendFormat:@"%c", decimalValue];
    }
    return string;

}

/*
 解析错误码
 
 @param code 返回提示
 */
+(NSString *)getNetworkErrorMessageWith:(NSInteger)code{
    NSString *errorMesg = kRequestFaildMessage;
    if(![self checkNetWork])//没有网络
    {
        return kWithoutNetworkMessage;
    }
    
    switch (code) {
        case -1001://NSURLErrorTimedOut
            errorMesg = @"网络请求超时";
            break;
        case -1005://NSURLErrorNetworkConnectionLost
            errorMesg = @"网络连接异常";
            break;
        case -1011://NSURLErrorBadServerResponse
            errorMesg = @"服务忙，请稍后再试";
            break;
        case -999://请求被取消了不提示
            errorMesg = @"";
            break;
    }
    return errorMesg;
}

#pragma mark -
#pragma mark - ================<网络、其他校验>===============
/**
 网络检查
 
 @return YES-有网络 NO-无网络
 */
+(BOOL)checkNetWork{
    
    BOOL isHaveNet = YES;
    Reachability *r = [Reachability reachabilityWithHostName:ROOT_URL];
    switch ([r currentReachabilityStatus]) {
        case NotReachable:{
            isHaveNet = NO;
            break;
        }
        case ReachableViaWiFi: case ReachableViaWWAN:{
            isHaveNet = YES;
            break;
        }
        default:{
            break;
        }
    }
    return isHaveNet;
}



@end
